/**
 * 
 */
package us.levk.remote.drmaa.client.impl;

import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.client.util.ClientFactory;
import org.ggf.drmaa.Session;
import org.ggf.drmaa.SessionFactory;

import us.levk.remote.drmaa.client.Configuration;
import us.levk.remote.drmaa.common.communication.ExtendedTypeFactory;
import us.levk.tools.collections.DefaultingMap;

/**
 * @author levk
 *
 */
public class SessionFactoryImpl extends SessionFactory {

  @SuppressWarnings ("unused") private static final transient Logger LOG = Logger.getLogger (SessionFactoryImpl.class);

  /* (non-Javadoc)
   * @see org.ggf.drmaa.SessionFactory#getSession()
   */
  @Override public Session getSession () { 
    return new SessionImpl (new DefaultingMap<URL, Map<Class<?>, Object>> (new HashMap<URL, Map<Class<?>, Object>> (), 
      new DefaultingMap.Factory<URL, Map<Class<?>, Object>> () {
        public Map<Class<?>, Object> make (final URL url) {
          if (url == null) throw new NullPointerException ("URL cannot be null");
          XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl ();
          config.setServerURL (url);
          config.setConnectionTimeout (0);
          config.setEnabledForExceptions (true);
          config.setEnabledForExtensions (true);
          config.setReplyTimeout (0);
          config.setGzipCompressing (true);
          config.setGzipRequesting (true);
          Configuration.Credential credential = Configuration.getConfiguration ().getCredential (url);
          if (credential != null) {
            config.setBasicUserName (credential.getUserName ());
            config.setBasicPassword (credential.getPassword ());
          }
          XmlRpcClient client = new XmlRpcClient ();
          client.setTypeFactory (new ExtendedTypeFactory (client));
          client.setConfig (config);
          final ClientFactory factory = new ClientFactory (client);
          return new DefaultingMap<Class<?>, Object> (new HashMap<Class<?>, Object> (), new DefaultingMap.Factory<Class<?>, Object> () {
            public Object make (Class<?> clazz) { return factory.newInstance (clazz); }
          }, true);
        }
    }, true));
  }
}
